<?php
/**
 * This is more or less a port of django humanize template tags
 */
class ImpSoft_View_Helper_Humanize {

	const DAYFORMAT = 'M d, Y';
	const TIMEFORMAT = 'g:ia';
	// I wonder if there will be issues with this when I go international ;) hee hee
	const DATEFORMAT = 'm/d/Y h:i:sa';
	
    public function humanize() {
    
        return $this;
    
    }
    /**
     * Converts an integer to its ordinal as a string. 1 is '1st', 2 is '2nd', etc.
     * @todo Optionally humanize number as well and default to true. 1000 is 1,000th, etc.
     */
    public function ordinal($value) {
	
		$value = (integer) $value;
		$ord = array('th','st','nd','rd','th','th','th','th','th','th');
		// special cases
		if (in_array($value % 100, array(11, 12, 13))) return sprintf("%d%s", $value, $ord[0]);
		return sprintf('%d%s', $value, $ord[$value % 10]);
	
	}
    /**
 	 * Converts a large integer to a friendly text representation. Works best for
 	 * numbers over 1 million. For example, 1000000 becomes '1.0 million', 1200000
 	 * becomes '1.2 million' and '1200000000' becomes '1.2 billion'.
 	 *
 	 * For now, don't send numbers larger than 2 billion to it.
     */
    public function intword($value) {
	
	    $value = (integer) $value;
	    if ($value < 1000000) {
	        return $value;
        }
	    if ($value < 1000000000) {
	        $new_value = $value / 1000000.0;
	        return sprintf("%.1f million", $new_value);
        }
	    if ($value < 1000000000000) {
	        $new_value = $value / 1000000000.0;
	        return sprintf("%.1f billon", $new_value);
        }
        /** Apparently, php doesn't support numbers this big... lame. I'm sure I could find
	        a work-around, but it's not a huge deal atm
	    if ($value < 1000000000000000) {
	        $new_value = $value / 1000000000000.0;
	        return sprintf("%.1f trillion", $new_value);
        }
        */
	    return $value;
	
	}
    /**
 	 * Converts a large integer to a friendly text representation. Works best for
 	 * numbers over 1 million. For example, 1000000 becomes '1.0 million', 1200000
 	 * becomes '1.2 million' and '1200000000' becomes '1.2 billion'.
 	 *
 	 * Because PHP can't work with numbers larger than 2 billion, I use strings instead,
 	 * this is proving to be VERY difficult to do. I'll get it, but I'm done messin with it for
 	 * now
	 * @todo: finish the string work-around
    public function intword($value) {
	
	    $str = (string) $value;
	    $digits = strlen($str);
	    // if less than a billion
	    if ($digits < 10) {
	    	// we can work with numbers this large
        	$new_value = ((int) $value) / 1000000.0;
	    	return sprintf("%.1f million", $new_value);
	    }
	    if ($digits < 13) { 
	    	// we can't work with numbers larger than 2 bil, so we need to do some trickery
	    	// find which position the dot should be
	    	$dotpos = $digits - 10 +1;
	    	// find how many digits we're going to show (how many past 10, which is a billion)
	        
	    	return $showing;
	    	// find the first part
	    	$pt1 = substr($str, 0, $dotpos);
	    	// and the second part
	    	$pt2 = substr($str, strlen($pt1), ($showing-strlen($pt1)));
	    	// convert to float
	    	$float = (float) "$pt1.$pt2";
	    	return sprintf("%.1f billion", $float);
	    	
	    }
	
	}
     */
    /**
     * Returns a "humanized" day - today, tomorrow, yesterday if relevant,
     * otherwise it returns the date in $format format
     * 
     * I am sure this is not the best way to do this, but it works
     */
    public function naturalDay($timestamp = null, $format = null) {
    
    	if (is_null($timestamp)) $timestamp = time();
    	if (is_null($format)) $format = self::DAYFORMAT;
    	
    	$oneday = 60*60*24;
    	$today = strtotime('today');
    	$tomorrow = $today + $oneday;
    	$yesterday = $today - $oneday;
    	// if time is 12:00 yesterday or more
    	if ($timestamp >= $yesterday) {
    		// if time is less than 12:00 the day after tomorrow
    		if ($timestamp < $tomorrow + $oneday && $timestamp > $today) {
    			// if time is less than 12:00 tomorrow
    			if ($timestamp < $tomorrow) {
    				return 'today';
    			}
    			return 'tomorrow';
    		}
    		return 'yesterday';
    	}
    	
    	return date($format, $timestamp);
    
    }
    /**
     * Returns a "humanized" time - so, if entry was today, it will say "about 16 minutes ago", "about 8 hours ago",
     * but if it isn't it will return the time formatted in $format format
     * 
     * I am sure this is not the best way to do this, but it works
     */
    public function naturalTime($timestamp = null, $format = null) {
    
    	if (is_null($timestamp)) $timestamp = time();
    	if (is_null($format)) $format = self::TIMEFORMAT;
    	
    	$now = time();
    	$hour = 60*60;
    	if ($this->naturalDay($timestamp, $format) == 'today') {
    		$hourago = $now - $hour;
    		$hourfromnow = $now + $hour;
    		// if timestamp passed in was after an hour ago...
    		if ($timestamp > $hourago) {
    			// if timestamp passed in is in the future...
    			if ($timestamp > $now) {
					// return how many minutes from now
					$seconds = $timestamp - $now;
					$minutes = (integer) round($seconds/60);
					// if more than 60 minutes ago, report in hours
					if ($minutes > 60) {
						$hours = round($minutes/60);
						return "in about $hours hours";
					}
					// if it got rounded down to zero, or it was one, report one
					if (!$minutes || $minutes === 1) return "just now";
					return "in about $minutes minutes";
    			}
				// return how many minutes from now
				$seconds = $now - $timestamp;
				$minutes = (integer) round($seconds/60);
				// if it got rounded down to zero, or it was one, report one
				if (!$minutes || $minutes === 1) return "just now";
				return "about $minutes minutes ago";
    		}
    	}
    	
    	return date($format, $timestamp);
    
    }
    /**
     * For now, this will only convert numbers 0-9
     * @todo Convert a number to it's spelled-out version. For instance, 1 becomes one, 307 becomes
     * three hundred seven, 28 becomes twenty-eight.
     */
	public function strNum($value) {
	
		$int = (integer) $value;
		$numbers = array('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
		if (isset($numbers[$value])) return $numbers[$value];
		return $value;
	
	}

}